package dryven.reflection;

import java.lang.reflect.Method;
import java.util.Iterator;

public class DeclaringMethodIterator implements Iterable<Method> {

	private Class<?> _baseType;
	private boolean _excludeObject;
	
	public DeclaringMethodIterator(Class<?> baseType) {
		this(baseType,true);
	}
	
	public DeclaringMethodIterator(Class<?> baseType, boolean excludeObject) {
		super();
		_baseType = baseType;
		_excludeObject = excludeObject;
	}



	@Override
	public Iterator<Method> iterator() {
		return new MethodIterator();
	}

	class MethodIterator implements Iterator<Method> {

		private Class<?> _currentType;
		private Method[] _currentDeclaringMethods;
		private int _index;
		
		public MethodIterator() {
			_currentType = _baseType;
			_currentDeclaringMethods = _currentType.getDeclaredMethods();
			_index = 0;
		}
		
		@Override
		public boolean hasNext() {
			return !(((_currentType.equals(Object.class) && !_excludeObject) || (_excludeObject && _currentType.getSuperclass().equals(Object.class))) && _index==_currentDeclaringMethods.length);
		}

		@Override
		public Method next() {
			while(_index==_currentDeclaringMethods.length) {
				_index = 0;
				_currentType = _currentType.getSuperclass();
				_currentDeclaringMethods = _currentType.getDeclaredMethods();
			}
			int currentIndex = _index;
			++_index;
			return _currentDeclaringMethods[currentIndex];
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
		
	}
}
